﻿using System;
using System.Collections.Generic;
using System.Text;
using SwinGame;
using System.Linq;
using NeuralNetworkPrototype;

namespace SimpleSurvival.src
{

    //-----------------------------------------------//
    //Extension - NeuralNetwork Integration
    #region NeuralNetwork mod - ---------------------//
    //-----------------------------------------------//
    //CLASS - NeuralNetworkManager.cs
    //-----------------------------------------------//
    //Hack class for implementing the neural network//
    //Made this new class so as little as possible existing
    //code is edited. New code > changing code (In this case)

    class NeuralNetworkManager
    {
        //Contains construction details
        //And mutation functionality
        //And training functionality
        INeuralNetMutator _mutator = new NeuralNetMutator();
        NeuralNetworkFactory _factory = new NeuralNetworkFactory();
        List<int> _defaultStructure = (new int[] { 2, 5, 5, 2 }.ToList());
        public INeuralNetMutator Mutator { get { return _mutator; } }
        public NeuralNetworkFactory Factory { get { return _factory; } }
        public List<int> Structure { get { return _defaultStructure; } }
        Random r = new Random();

        //Wrapper to create an enemy ai with neural network
        public void CreateEnemyUnit(Map m, EntityFactory ef)
        {
            IUnit u = ef.MakeUnit("SLIME", new Vector { X = r.Next(600), Y = r.Next(600) });
            AIUnitController _aiController = new AIUnitController(
                Factory.Make(Structure),
                Mutator);
            _aiController.LinkToObject(u);
        }

        public void Train(Map m, EntityFactory ef)
        {

            for (int i = 0; i < m.Units.Count; i++)
            {
                //random mutate chance
                if (r.Next(100) <= 2)
                {
                    AIUnitController a = m.Units[i].Entity.Controller as AIUnitController;
                    if (a != null) { a.Mutator.Nuke(-1, 1, 0.05, a.NeuralNet); }
                }

                //if enemy unit is outside of cam, kill and spawn a new enemy ai
                if (m.Units[i].Entity.Position.X < 0 || m.Units[i].Entity.Position.X > 600 ||
                    m.Units[i].Entity.Position.Y < 0 || m.Units[i].Entity.Position.Y > 600)
                {
                        m.RemoveEntity(m.Units[i].Entity);
                        CreateEnemyUnit(m, ef);

                }
            }
        }


    }
    #endregion

    //-----------------------------------------------//
    //CLASS - GameState.cs
    //-----------------------------------------------//
    //The state when actually playing the game
    //Sort of like a facade pattern
    public class GameState : State
    {   
        //Next time - Should convert some of these into interface
        //equivalents to promote loose coupling.

        //-----------------------------------------------//
        //Extension - NeuralNetwork Integration
        #region NeuralNetwork mod - ---------------------//
        NeuralNetworkManager neuralNetworkManager = null;
        #endregion 

        Map map = null;
        ICamera camera = null;
        CameraController cameraController = null;
        EntityDrawer entityDrawer = null;
        EntityDefinitions entityDefinitions = null;
        EntityFactory entityFactory = null;

        public GameState(Game g) : base(g) { IsTransparent = false; }

        public override void LoadContent()
        {
            //-----------------------------------------------//
            //Extension - NeuralNetwork Integration
            #region NeuralNetwork mod - ---------------------//
            neuralNetworkManager = new NeuralNetworkManager();
            #endregion

            entityDefinitions = new EntityDefinitions();            //Load content
            entityDrawer = new EntityDrawer(entityDefinitions);     
            map = new Map();
            camera = new Camera();
            cameraController = new CameraController(camera);
            entityFactory = new EntityFactory(entityDefinitions, entityDrawer, map);
            map.PopulateMap(entityFactory);                         //Create things on the map

            //Move player and controller stuff out of here in the next iter.
            const int PlayerId = 0;                                 
            UnitControllers _playerController = new UnitControllers(camera, entityFactory);

            //-----------------------------------------------//
            //Extension - NeuralNetwork Integration
            #region NeuralNetwork mod - ---------------------//
            for (int i = 0; i < 25; i++)
            {
                neuralNetworkManager.CreateEnemyUnit(map, entityFactory);
            }
            #endregion

            _playerController.LinkToObject(map.Units[PlayerId]);

            //set up terrain
            base.LoadContent();
        }
        public override void Update(double dt)
        {
            map.UpdateAllEntitys(dt);
            cameraController.GetInput(dt);
            neuralNetworkManager.Train(map, entityFactory);
            base.Update(dt);
        }
        public override void Draw(double dt)
        {
            entityDrawer.DrawEntityList(map.Entitys,camera,entityDefinitions);
            base.Draw(dt);
        }
    }
}
